package com.hyq.grid.common;

import org.gdal.gdal.Band;
import org.gdal.gdal.Dataset;
import org.gdal.gdal.gdal;
import org.gdal.gdalconst.gdalconstConstants;
import org.gdal.ogr.*;
import org.gdal.osr.SpatialReference;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class gdalTool {

    public gdalTool() {
    }

    public static void getShapInf(String ShapPath) {

//        注册所有驱动
        ogr.RegisterAll();
//        配置GDAL_DATA路径
        gdal.SetConfigOption("GDAL_DATA", "D:\\SDK\\GDAL\\release-1911-x64-gdal-2-4-0-mapserver-7-2-1\\bin\\gdal-data");
//        支持中文路径
        gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
//        属性表字段支持中文
        gdal.SetConfigOption("SHAPE_ENCODING", "");
//        读取数据
        String strDriverName = "ESRI Shapefile";
//        创建文件，根据strDriverName扩展名自动判断驱动类型
        org.gdal.ogr.Driver oDriver = ogr.GetDriverByName(strDriverName);
        if (oDriver == null) {
            System.out.println(strDriverName + "驱动不可用！\n");
            return;
        }

        DataSource dataSource = oDriver.Open(ShapPath);
//        获取图层
        Layer layer = dataSource.GetLayer(0);

        String strlayerName = layer.GetName();
        System.out.println("图层名称：" + strlayerName);

        SpatialReference spatialReference = layer.GetSpatialRef();
        System.out.println("空间参考坐标系：" + spatialReference.GetAttrValue("AUTHORITY", 0) + spatialReference.GetAttrValue("AUTHORITY", 1));

        double[] layerExtent = layer.GetExtent();
        System.out.println("图层范围：minx:" + layerExtent[0] + ", maxx:" + layerExtent[1] + ", miny:" + layerExtent[2] + ", maxy:" + layerExtent[3]);


        FeatureDefn featureDefn = layer.GetLayerDefn();
        int filedCount = featureDefn.GetFieldCount();

        Map<String, Object> fieldMap = new HashMap<>();
        for (int i = 0; i < filedCount; i++) {
            FieldDefn fieldDefn = featureDefn.GetFieldDefn(i);
//            得到属性字段类型
            int fieldType = fieldDefn.GetFieldType();
            String fieldTypeName = fieldDefn.GetFieldTypeName(fieldType);
//            的到属性字段名称
            String fieldName = fieldDefn.GetName();
            fieldMap.put("filed" + i, fieldName);
        }
        long featureCount = layer.GetFeatureCount();
        System.out.println("图层要素个数：" + featureCount);


        for (int i = 0; i < featureCount; i++) {
            Feature feature = layer.GetFeature(i);

            Geometry geometry = feature.GetGeometryRef();

//            转为json
            String geometryJson = geometry.ExportToJson();
//            获取边界坐标
            double[][] boundaryPoints = geometry.GetBoundary().GetPoints();

            Object[] arr = fieldMap.values().toArray();
            for (int k = 0; k < arr.length; k++) {
                String fvalue = feature.GetFieldAsString(arr[k].toString());
                System.out.println("属性名称：" + arr[k].toString() + " 属性值：" + fvalue);
            }
            System.out.println("要素类型：" + geometry.GetGeometryName() + " 边界坐标：" + geometryJson.substring(geometryJson.lastIndexOf(":") + 1, geometryJson.length()));
            System.out.println();
        }

    }

    public static void shapTojson(String ShapPath) {
        // 注册所有的驱动
        ogr.RegisterAll();
        // 支持中文路径
        gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
        // fapia属性表字段支持中文
        gdal.SetConfigOption("SHAPE_ENCODING", "");


        //打开文件
        DataSource ds = ogr.Open(ShapPath, 0);
        if (ds == null) {
            System.out.println("打开文件失败！");
            return;
        }
        System.out.println("打开文件成功！");
        Driver dv = ogr.GetDriverByName("GeoJSON");
        if (dv == null) {
            System.out.println("打开驱动失败！");
            return;
        }
        System.out.println("打开驱动成功！");

        dv.CopyDataSource(ds, "D:\\edgesDownload\\node.json");
        System.out.println("转换成功！");
    }

    public static Map getDemInf(String DemPath) {


//        注册所有驱动
        ogr.RegisterAll();
//        配置GDAL_DATA路径
        gdal.SetConfigOption("GDAL_DATA", "D:\\GDAL\\GDAL\\release-1911-x64-gdal-2-4-0-mapserver-7-2-1\\bin\\gdal-data");
//        支持中文路径
        gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
//        属性表字段支持中文
        gdal.SetConfigOption("SHAPE_ENCODING", "");

        Dataset dataset = gdal.Open(DemPath, gdalconstConstants.GA_ReadOnly);
        if (dataset == null) {
            System.out.println("打开文件失败！");
            return null;
        }
        System.out.println("打开DEM文件成功！");
        System.out.println("******开始读取DEM数据******");

        org.gdal.gdal.Driver driver = dataset.GetDriver();

//        获取Dem大小
        int XSize = dataset.GetRasterXSize();
        int YSize = dataset.GetRasterYSize();
//        获取栅格单元大小
        double rasterCellLength;
        System.out.println("Driver: " + driver.getShortName() + driver.getLongName());
        System.out.println("Size is " + XSize + "," + YSize);

        Band band = dataset.GetRasterBand(1);
        double[] databuf = new double[XSize * YSize];
        band.ReadRaster(0, 0, XSize, YSize, databuf);


//        获取屏幕坐标转换到实际地理坐标的参数
        double[] gt = new double[6];
        dataset.GetGeoTransform(gt);
//        存储DEM坐标信息Map（X,Y,Z）
        List<Double[]> rastinf = new ArrayList<>();
        List<Double[]> border = new ArrayList<>();
        List<Double[]> node = new ArrayList<>();

        List<Double[]> borderTop = new ArrayList<>();
        List<Double[]> borderRight = new ArrayList<>();
        List<Double[]> borderBotoom = new ArrayList<>();
        List<Double[]> borderLeft = new ArrayList<>();
//        符合屏幕坐标系
        Double[][][] nodescreen = new Double[YSize][XSize][3];
        List<Map> demElement = new ArrayList<>(); //单元
        for (int i = 0; i < YSize; i++) {
            for (int j = 0; j < XSize; j++) {

                Double[] coor = new Double[3];
                Double X = gt[0] + j * gt[1] + i * gt[2];
                Double Y = gt[3] + j * gt[4] + i * gt[5];

                coor[0] = X;
                coor[1] = Y;
                coor[2] = databuf[i * XSize + j];
                nodescreen[YSize - 1 - i][j][0] = X;
                nodescreen[YSize - 1 - i][j][1] = Y;
                nodescreen[YSize - 1 - i][j][2] = databuf[i * XSize + j];

                rastinf.add(coor);

                if (i == 0) {
                    borderTop.add(coor);
                } else if (i == (YSize - 1)) {
                    borderBotoom.add(coor);
                } else if (j == 0) {
                    borderLeft.add(coor);
                } else if (j == (XSize - 1)) {
                    borderRight.add(coor);
                }

            }
        }

        if (nodescreen[0][0][0].equals(nodescreen[0][1][0])) {
            rasterCellLength =Math.abs(nodescreen[0][0][1] - nodescreen[0][1][1]) ;
        } else {
            rasterCellLength =Math.abs(nodescreen[0][0][0] - nodescreen[0][1][0]) ;
        }



//        按顺指针组织边界单元
        for (Double[] element : borderTop) {
            border.add(element);
        }
        for (int i = 1; i < borderRight.size(); i++) {
            border.add(borderRight.get(i));
        }
        for (int i = (borderBotoom.size() - 2); i >= 0; i--) {
            border.add(borderBotoom.get(i));
        }
        for (int i = (borderLeft.size() - 2); i > 0; i--) {
            border.add(borderLeft.get(i));
        }

//        System.out.println("******DEM坐标数据******");

//        ******DEM坐标数据******
//        当前单元坐标
        Double x,y,z;
//        DEM范围：MinX,MaxX,MinY,MaxY,MinZ,MaxZ
        Double[] demRange = new Double[]{nodescreen[0][0][0],nodescreen[0][0][0],nodescreen[0][0][1],nodescreen[0][0][1],nodescreen[0][0][2],nodescreen[0][0][2]};
        for (int i = 0; i < YSize; i++) {
            for (int j = 0; j < XSize; j++) {

                HashMap<String,Object> demCell = new HashMap<>();

                x = nodescreen[i][j][0];
                y = nodescreen[i][j][1];
                z = nodescreen[i][j][2];

                node.add(new Double[]{nodescreen[i][j][0], nodescreen[i][j][1], nodescreen[i][j][2]});

                Double[] elementX = new Double[4];
                Double[] elementY = new Double[4];

                elementX[0] = x - rasterCellLength / 2;
                elementY[0] = y - rasterCellLength / 2;

                elementX[1] = x + rasterCellLength / 2;
                elementY[1] = y - rasterCellLength / 2;

                elementX[2] = x + rasterCellLength / 2;
                elementY[2] = y + rasterCellLength / 2;

                elementX[3] = x - rasterCellLength / 2;
                elementY[3] = y + rasterCellLength / 2;

                demCell.put("X",elementX);
                demCell.put("Y", elementY);
                demCell.put("Z", z);
                demElement.add(demCell);

                if (x < demRange[0]) demRange[0] = x;
                if (x > demRange[1]) demRange[1] = x;

                if (y < demRange[2]) demRange[2] = y;
                if (y > demRange[3]) demRange[3] = y;

                if (z < demRange[4]) demRange[4] = z;
                if (z > demRange[5]) demRange[5] = z;

            }
        }



        Map<String, Object> outPutData = new HashMap<>();
        outPutData.put("node", node);
        outPutData.put("border", border);
        outPutData.put("xsize", XSize);
        outPutData.put("ysize", YSize);
        outPutData.put("range", demRange);
        outPutData.put("element",demElement);
        System.out.println("******DEM数据读取成功******");
        return outPutData;
    }
}

